-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Don't ICE on pending obligations from deep normalization in a loop #140021
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
This PR changes a file inside |
let mut errors = fulfill_cx.select_all_or_error(self.infcx); | ||
// Drain pending obligations too, since deep normalization may happen | ||
// in a loop and we don't want to trigger the assertion on the next | ||
// iteration due to pending obligations we've left over. | ||
errors.extend(fulfill_cx.collect_remaining_errors(self.infcx)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm, fn select_all_or_error
is currently implemented as
fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E> {
let errors = self.select_where_possible(infcx);
if !errors.is_empty() {
return errors;
}
self.collect_remaining_errors(infcx)
}
it feels a bit footgunny to not add the overflowing obligations if there are other errors. I think changing the if errors.is_empty()
branch to also add the remaining errors would be better 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
or no, in case select_where_possible
returns an error, we want to ignore overflow and ambiguity errors. I think we also want to ignore these ambiguity errors here, so maybe change this to
let errors = fulfill_cx.select_all_or_error(self.infcx);
if errors.is_empty() {
Ok(self.infcx.resolve_vars_if_possible(value))
} else {
// In case normalization resulted in an error, we want to
// drain any still ambiguous goal to avoid triggering the
// assertion on the next iteration.
let _ = fulfill_cx.collect_remaining_errors(self.infcx));
Err(errors)
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
alternatively we could drop the remaining obligations in the !errors.is_empty()
branch in select_all_or_error
itself? 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
alternatively we could drop the remaining obligations in the
!errors.is_empty()
branch inselect_all_or_error
itself? 🤔
Hm, feels like a much larger and more subtle change. I'd rather keep it located to deep normalization.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
or no, in case select_where_possible returns an error, we want to ignore overflow and ambiguity errors. I think we also want to ignore these ambiguity errors here, so maybe change this to [...]
Functionally equivalent to what I have right now, but I guess alright.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Functionally equivalent to what I have right now, but I guess alright.
Correction -- not functionally equivalent, but doesn't matter for UI tests. I originally had let _ = fulfill_cx.collect_remaining_errors(self.infcx))
on the good path of deep norm too, but it felt spooky. I guess it's fine though.
12269e9
to
47911eb
Compare
See the comment I left inline in
compiler/rustc_trait_selection/src/traits/normalize.rs
.Fixes #133868
r? lcnr